﻿using Common.Class;
using SqlSugar;
using System.Reflection;

namespace Common.Class
{
    public class SugarHelper
    {
        /// <summary>
        /// 获取SqlSugarClient对象
        /// </summary>
        /// <param name="_DbType">数据库类型</param>
        /// <param name="_ConnectStr">数据库连接字符串</param>
        /// <param name="_CommandTimeOut">执行超时时间(秒)</param>
        /// <param name="_IsDBLog">是否记录SQL执行日志</param>
        /// <param name="AutoFree">是否自动释放连接</param>
        /// <returns></returns>
        public static SqlSugarClient GetSqlSugarClient(SqlSugar.DbType _DbType = SqlSugar.DbType.MySql, string _ConnectStr = "", int _CommandTimeOut = 30, bool _IsDBLog = false, bool AutoFree = true)
        {
            SqlSugarClient _db = null;
            if (_DbType == DbType.Sqlite)
            {
                if (_ConnectStr.ToLower().IndexOf("password=") > -1)
                {
                    _db = CacheHelper.CacheGet(_ConnectStr) as SqlSugarClient;
                }
            }

            if (_db == null)
            {
                _db = new SqlSugarClient(new ConnectionConfig()
                {
                    ConnectionString = _ConnectStr,
                    DbType = _DbType,
                    InitKeyType = InitKeyType.Attribute,//从特性读取主键和自增列信息
                    IsAutoCloseConnection = AutoFree,//开启自动释放模式和EF原理一样我就不多解释了

                });
                CacheHelper.CacheAdd(_ConnectStr, _db, null, 60 * 60 * 24);
            }

            _db.Ado.CommandTimeOut = _CommandTimeOut;

            //调式代码 用来输出SQL 
            _db.Aop.OnLogExecuting = (sql, pars) =>
            {
                if (_IsDBLog)
                {
                    Console.WriteLine(sql + "\r\n" + _db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value))); 
                }
            };

            return _db;
        }

        /// <summary>
        /// 返回一个只有修改属性的model，其它属性为null值
        /// </summary>
        /// <typeparam name="T">类</typeparam>
        /// <param name="_Model">原model</param>
        /// <returns></returns>
        public static T CreateUpdateModel<T>(T _Model) where T : class, new()
        {
            T _ro = null;

            PropertyInfo _findedPropertyInfo = _Model.GetType().GetProperty("ChangeProperty");
            if (_findedPropertyInfo == null)
            {
                return _Model;
            }
            else
            {
                List<string> _changeProperty = _findedPropertyInfo.GetValue(_Model, null) as List<string>;
                if (_changeProperty == null)
                {
                    return _Model;
                }
                else
                {
                    //复制修改过得属性
                    if (_changeProperty.Count > 0)
                    {
                        _ro = new T();
                        foreach (string _propertyName in _changeProperty)
                        {
                            object _proValue = _Model.GetType().GetProperty(_propertyName).GetValue(_Model, null);
                            _ro.GetType().GetProperty(_propertyName).SetValue(_ro, _proValue);
                        }
                        //复制主键属性
                        Type t = typeof(T);
                        foreach (PropertyInfo _prop in t.GetProperties())
                        {
                            foreach (SugarColumn _attr in _prop.GetCustomAttributes(typeof(SugarColumn), true))
                            {
                                if (_attr.IsPrimaryKey)
                                {
                                    object _proValue = _Model.GetType().GetProperty(_prop.Name).GetValue(_Model, null);
                                    _ro.GetType().GetProperty(_prop.Name).SetValue(_ro, _proValue);
                                }
                            }
                        }
                    }
                    return _ro;
                }

            }
        }

        /// <summary>
        /// 将修改过的model字段修改原model并返回，用于只变动修改的字段，防止并发的时候把未修改的内容都更新
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="oldModel">待更新的model</param>
        /// <param name="updateModel">有修改字段的model</param>
        /// <returns></returns>
        public static T UpdateModel<T>(T oldModel, T updateModel)
        {
            T _ro = oldModel;

            PropertyInfo _findedPropertyInfo = updateModel.GetType().GetProperty("ChangeProperty");
            if (_findedPropertyInfo == null)
            {
                return updateModel;
            }
            else
            {
                List<string> _changeProperty = _findedPropertyInfo.GetValue(updateModel, null) as List<string>;
                if (_changeProperty == null)
                {
                    return updateModel;
                }
                else
                {
                    //复制修改过得属性
                    if (_changeProperty.Count > 0)
                    {
                        foreach (string _propertyName in _changeProperty)
                        {
                            object _proValue = updateModel.GetType().GetProperty(_propertyName).GetValue(updateModel, null);
                            _ro.GetType().GetProperty(_propertyName).SetValue(_ro, _proValue);
                        }
                    }
                    return _ro;
                }

            }
        }

    }
}
